/**
 * Copyright [2019] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.pscan;

import lombok.*;
import org.apache.commons.collections.CollectionUtils;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @project-name:coffice-toolbox
 * @package-name:com.hyts.pscan
 * @author:LiBo/Alex
 * @create-date:2020-04-07 11:21
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description:
 */
public class PathScanner {

    /**
     * 获取一级菜单资源信息（）不进行深度递归遍历
     * @return
     */
    @SneakyThrows(Exception.class)
    public static List<Path> getOneLevelResources(String directPath){
        Path dir = Paths.get(directPath);
        List<Path> pathList = new ArrayList<>();
        @Cleanup DirectoryStream<Path> stream = Files.newDirectoryStream(dir);
        stream.forEach(pathList::add);
        return pathList;
    }

    /**
     * 获取一级菜单资源信息（）不进行深度递归遍历
     * @return
     */
    @SneakyThrows(Exception.class)
    public static List<Path> getOneLevelResources(Path directPath){
        @Cleanup Stream<Path> stream = Files.list(directPath);
        return stream.collect(Collectors.toList());
    }
    /**
     * 获取所有菜单资源信息（）进行深度递归遍历
     * @param directPath
     * @return
     */
    @SneakyThrows(Exception.class)
    public static List<Path> getFullResources(String directPath){
        Path startingDir = Paths.get(directPath);
        List<Path> result = new LinkedList<>();
        Files.walkFileTree(startingDir,new FindAllResourceVisitor(result));
        return result;
    }

    @SneakyThrows(Exception.class)
    public static List<Path> getFullResourcesByExclude(String directPath,List<String> extNameList){
        Path startingDir = Paths.get(directPath);
        List<Path> result = new LinkedList<>();
        Files.walkFileTree(startingDir,new FindExcludeExtNameVisitor(result,extNameList));
        return result;
    }

    @SneakyThrows(Exception.class)
    public static List<Path> getFullResourcesByInclude(String directPath,List<String> extNameList){
        Path startingDir = Paths.get(directPath);
        List<Path> result = new LinkedList<>();
        Files.walkFileTree(startingDir,new FindIncludeExtNameVisitor(result,extNameList));
        return result;
    }

    @SneakyThrows(Exception.class)
    public static List<Path> getFullResourcesByInclude(String directPath,String extNameList){
        Path startingDir = Paths.get(directPath);
        List<Path> result = new LinkedList<>();
        Files.walkFileTree(startingDir,new FindIncludeExtNameVisitor(result,new ArrayList<String>(){{add(extNameList);}}));
        return result;
    }

    @SneakyThrows(Exception.class)
    public static List<Path> getFullResourcesByExclude(String directPath,String extNameList){
        Path startingDir = Paths.get(directPath);
        List<Path> result = new LinkedList<>();
        Files.walkFileTree(startingDir,new FindExcludeExtNameVisitor(result,new ArrayList<String>(){{add(extNameList);}}));
        return result;
    }

    /**
     * 获取所有菜单资源信息（）进行深度递归遍历
     * @param directPath
     * @return
     */
    @SneakyThrows(Exception.class)
    public static List<Path> getResourcesByCondition(String directPath,SimpleFileVisitor<Path> fileVisitor){
        Path startingDir = Paths.get(directPath);
        List<Path> result = new LinkedList<>();
        Files.walkFileTree(startingDir, fileVisitor);
        return result;
    }
    /**
     *
     */
     @Getter
     @Setter
     @NoArgsConstructor
     @AllArgsConstructor
     private static class FindExcludeExtNameVisitor extends SimpleFileVisitor<Path>{
         /**
         * 数据结果
         */
        private List<Path> result;
        /**
         * 数据信息过滤扩展名
         */
        private List<String> excludeFileExtNames;

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
             if(CollectionUtils.isNotEmpty(excludeFileExtNames) && excludeFileExtNames.parallelStream().
                     noneMatch(param->file.toString().endsWith(param))){
                 result.add(file.getFileName());
             }
             return FileVisitResult.CONTINUE;
        }
     }


    /**
     *
     */
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    private static class FindIncludeExtNameVisitor extends SimpleFileVisitor<Path>{
        /**
         * 数据结果
         */
        private List<Path> result;
        /**
         * 数据信息过滤扩展名
         */
        private List<String> excludeFileExtNames;

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
            if(CollectionUtils.isNotEmpty(excludeFileExtNames) && excludeFileExtNames.parallelStream().
                    anyMatch(param->file.toString().endsWith(param))){
                result.add(file.getFileName());
            }
            return FileVisitResult.CONTINUE;
        }
    }

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    private static class FindAllResourceVisitor extends SimpleFileVisitor<Path>{
        /**
         * 数据结果
         */
        private List<Path> result;

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
                result.add(file.getFileName());
                return FileVisitResult.CONTINUE;
        }
    }
    public static void main(String[] args){
        System.out.println(PathScanner.getFullResourcesByInclude("D:\\other_space\\coffice-toolbox",".java").size());
    }

}
